using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using SharpWind.Network;
using Lidgren.Library.Network;

namespace SharpWindServer
{
	public partial class MainForm : Form
	{
		#region Fields

		private DateTime startTime = DateTime.Now;

		#endregion

		#region Constructor

		public MainForm()
		{
			InitializeComponent();

			Server.Instance.PlayerConnected += new SharpWind.Network.ConnectionEventHandler(Server_PlayerConnected);
			Server.Instance.PlayerDisconnected += new ConnectionEventHandler(Server_PlayerDisconnected);
			Server.Instance.ServerShutdown += new StatusEventHandler(Server_ServerShutodown);
			Server.Instance.Log += new NetworkLogEventHandler(Server_Log);
		}

		#endregion

		#region Form Events Methods

		private void MainForm_Load( object sender, EventArgs e )
		{
			this.cbMaxConnections.SelectedIndex = 0;
			SetOptionsEnabled( true );
		}

		#endregion

		#region Controls Events Methods

		private void tbServerStart_Click( object sender, EventArgs e )
		{
			Server.Instance.Start();
			this.tbServerStart.Enabled	= false;
			this.tbServerStop.Enabled	= true;
			this.startTime = DateTime.Now;

			SetOptionsEnabled( false );
		}

		private void tbServerStop_Click( object sender, EventArgs e )
		{
			Server.Instance.Shutdown( Reason.ServerQuit );
			this.tbServerStart.Enabled	= true;
			this.tbServerStop.Enabled	= false;

			SetOptionsEnabled( true );
		}

		private void tbClose_Click( object sender, EventArgs e )
		{
			Server.Instance.Shutdown( Reason.ServerQuit );
			Application.Exit();
		}

		private void lvPlayers_MouseDown( object sender, MouseEventArgs e )
		{
			if( e.Button == MouseButtons.Right )
			{
				ListViewHitTestInfo info = this.lvPlayers.HitTest( e.Location );
				if( info.Item == null )
				{
					this.lvPlayers.SelectedItems.Clear();
					return;
				}

				if( this.lvPlayers.SelectedItems.Count == 0 )
				{
					info = this.lvPlayers.HitTest( e.Location );
					if( info.Item != null )
					{
						this.contextMenuStrip.Show( this.lvPlayers, e.Location );
					}
				}
				else if( this.lvPlayers.SelectedItems.Count == 1 )
				{
					this.lvPlayers.SelectedItems.Clear();
					this.contextMenuStrip.Show( this.lvPlayers, e.Location );
				}
				else
				{
					this.contextMenuStrip.Show( this.lvPlayers, e.Location );
				}
			}
		}

		private void kickToolStripMenuItem_Click( object sender, EventArgs e )
		{
			foreach( ListViewItem item in this.lvPlayers.SelectedItems )
			{
				Connection connection = Server.Instance[item.Text];
				if( connection != null )
				{
					connection.Disconnect( Reason.PlayerKicked );
				}
			}
		}

		private void cbMaxConnections_KeyPress( object sender, KeyPressEventArgs e )
		{
			e.Handled = true;
		}

		private void cbPassword_CheckedChanged( object sender, EventArgs e )
		{
			this.tbPassword.Enabled = cbPassword.Checked;
		}

		private void btnSave_Click( object sender, EventArgs e )
		{
			Server.Instance.MaxConnections  = int.Parse( (string)this.cbMaxConnections.SelectedItem );
			Server.Instance.PasswordEnabled = this.cbPassword.Checked;
			Server.Instance.Password		= this.tbPassword.Text;
		}

		#endregion

		#region Server Events Methods

		private void Server_PlayerConnected( object sender, ConnectionEventArgs e )
		{
			ListViewItem item	= new ListViewItem( e.Connection.PlayerName );
			item.Tag			= e.Connection;
			item.SubItems.Add( e.Connection.EndPoint.ToString() );
			item.SubItems.Add( e.Connection.AverageRoundtripTime.ToString() );

			this.lvPlayers.Items.Add( item );
			InsertLog( DateTime.Now, NetLogEntryType.Info.ToString(), "Serever_PlayerConnected() in MainForm", e.Connection.PlayerName + " " + e.Reason.ToLower() );

			this.timer.Enabled = true;
		}

		private void Server_PlayerDisconnected( object sender, ConnectionEventArgs e )
		{
			foreach( ListViewItem item in this.lvPlayers.Items )
			{
				if( item.Text.Equals( e.Connection.PlayerName ) )
				{
					this.lvPlayers.Items.Remove( item );
					InsertLog( DateTime.Now, NetLogEntryType.Info.ToString(), "Serever_PlayerDisconnected() in MainForm", e.Connection.PlayerName + " " + e.Reason.ToLower() );

					if( this.lvPlayers.Items.Count == 0 )
					{
						this.timer.Enabled = false;
					}

					return;
				}
			}
		}

		private void Server_ServerShutodown( object sender, StatusEventArgs e )
		{
			this.lvPlayers.Items.Clear();
		}

		private void Server_Log( object sender, NetworkLogEventArgs e )
		{
			DateTime time = this.startTime.AddMilliseconds( e.Entry.TimeMillis );
			
			InsertLog( time, e.Entry.Type.ToString(), e.Entry.Where, e.Entry.What );
		}

		#endregion

		#region Helper Methods

		private void InsertLog( DateTime time, string type, string where, string what )
		{
			StringBuilder sb = new StringBuilder();
			sb.AppendFormat( "{0} - {1}: {2} - {3}", time.ToLongTimeString(), type, where, what );

			this.lbLog.Items.Insert( 0, sb.ToString() );
		}

		private void timer_Tick( object sender, EventArgs e )
		{
			foreach( ListViewItem item in lvPlayers.Items )
			{
				string playerName = item.Text;

				Connection connection = Server.Instance[playerName];
				if( connection != null )
				{
					item.SubItems[2].Text = connection.AverageRoundtripTime.ToString();
				}
			}
		}

		private void SetOptionsEnabled( bool value )
		{
			this.cbMaxConnections.Enabled	= value;
			this.cbPassword.Enabled			= value;
			this.tbPassword.Enabled			= this.cbPassword.Checked;
			this.btnSave.Enabled			= value;
		}

		#endregion
	}
}